using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using UnityEngine;
using System.Reflection;
using UnityEditor;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;

namespace Mars.ShaderAnalysis
{
    public static class EditorTools
    {
        #region 路径相关

        private static string _projectPath;

        /// <summary>
        /// 项目路径
        /// </summary>
        public static string projectPath
        {
            get
            {
                if (string.IsNullOrEmpty(_projectPath))
                {
                    _projectPath = Application.dataPath.Replace("Assets", string.Empty);
                }

                return _projectPath;
            }
        }

        /// <summary>
        /// 当前场景文件夹路径
        /// </summary>
        public static string currentSceneFolderPath
        {
            get
            {
                //当前场景
                Scene activeScene = SceneManager.GetActiveScene();
                string path = activeScene.path;
                if (string.IsNullOrEmpty(path))
                {
                    return "";
                }

                return path.Remove(path.LastIndexOf("/") + 1, path.Length - path.LastIndexOf("/") - 1);
            }
        }

        /// <summary>
        /// 变换为项目Assets相对路径
        /// </summary>
        public static string ChangeToRelativePath(string fullPath)
        {
            return fullPath.Replace(projectPath, string.Empty);
        }

        /// <summary>
        /// 变换为绝对路径
        /// </summary>
        public static string ChangeToFullPath(string relativePath)
        {
            return projectPath + relativePath;
        }

        #endregion

        #region 文件操作

        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="srcPath"></param>
        /// <param name="tarPath"></param>
        public static void CopyFile(string srcPath, string tarPath, bool copyWithMeta)
        {
            if (string.IsNullOrEmpty(srcPath) || string.IsNullOrEmpty(tarPath))
            {
                Debug.Log("路径不能为空");
                return;
            }

            srcPath = srcPath.Replace("/", "\\");
            if (!File.Exists(srcPath))
            {
                Debug.Log("不存在路径 srcPath = " + srcPath);
                return;
            }

            tarPath = tarPath.Replace("/", "\\");
            //创建文件夹
            string[] splitsTar = tarPath.Split("\\");
            //第一个是什么盘
            string dPathTar = splitsTar[0];
            //从第二个开始遍历，到n-1个
            for (int i = 1; i < splitsTar.Length - 1; i++)
            {
                dPathTar += "\\";
                dPathTar += splitsTar[i];
                if (!Directory.Exists(dPathTar))
                {
                    Directory.CreateDirectory(dPathTar);
                }
            }

            //复制文件
            if (File.Exists(tarPath))
            {
                File.Copy(srcPath, tarPath, true);
            }
            else
            {
                File.Copy(srcPath, tarPath);
            }

            if (copyWithMeta)
            {
                if (File.Exists(srcPath + ".meta"))
                {
                    File.Copy(srcPath + ".meta", tarPath + ".meta", true);
                }
            }
        }

        /// <summary>
        /// 复制文件夹
        /// </summary>
        /// <param name="srcPath"></param>
        /// <param name="tarPath"></param>
        public static void CopyFolder(string srcPath, string tarPath, bool copyWithMeta)
        {
            if (string.IsNullOrEmpty(srcPath) || string.IsNullOrEmpty(tarPath))
            {
                Debug.Log("路径不能为空");
                return;
            }

            srcPath = srcPath.Replace("/", "\\");
            if (!Directory.Exists(srcPath))
            {
                Debug.Log("不存在路径 srcPath = " + srcPath);
                return;
            }

            //不存在则创建文件夹
            tarPath = tarPath.Replace("/", "\\");
            if (!Directory.Exists(tarPath))
            {
                Directory.CreateDirectory(tarPath);
            }

            //复制文件夹里的文件
            string[] filePathArray = Directory.GetFiles(srcPath);
            foreach (string fSrcPath in filePathArray)
            {
                string fTarPath = tarPath + "\\" + fSrcPath.Substring(srcPath.Length + 1);
                if (File.Exists(fTarPath))
                {
                    File.Copy(fSrcPath, fTarPath, true);
                }
                else
                {
                    File.Copy(fSrcPath, fTarPath);
                }
            }

            //递归复制文件夹
            string[] directoryPathArray = Directory.GetDirectories(srcPath);
            foreach (string dSrcPath in directoryPathArray)
            {
                string dTarPath = tarPath + "\\" + dSrcPath.Substring(srcPath.Length + 1);
                CopyFolder(dSrcPath, dTarPath, false);
            }

            if (copyWithMeta)
            {
                if (File.Exists(srcPath + ".meta"))
                {
                    File.Copy(srcPath + ".meta", tarPath + ".meta", true);
                }
            }
        }

        /// <summary>
        /// 选中Windows文件
        /// </summary>
        /// <param name="path"></param>
        public static void SelectWindowsFile(string path)
        {
            if (!string.IsNullOrEmpty(path))
            {
                path = path.Replace("/", "\\");
                if (!File.Exists(path))
                {
                    Debug.LogError("No File: " + path);
                    return;
                }

                path = string.Format("/Select, {0}", path);

                //可能360不信任
                System.Diagnostics.Process.Start("explorer.exe", path);
            }
        }

        /// <summary>
        /// 选中Windows文件夹
        /// </summary>
        /// <param name="path"></param>
        public static void SelectWindowsDirectory(string path)
        {
            if (!string.IsNullOrEmpty(path))
            {
                path = path.Replace("/", "\\");

                if (!Directory.Exists(path))
                {
                    Debug.LogError("No Directory: " + path);
                    return;
                }

                //可能360不信任
                System.Diagnostics.Process.Start("explorer.exe", path);
            }
        }

        #endregion

        #region 选中相关

        /// <summary>
        /// 获取当前选中列表的路径
        /// </summary>
        /// <returns></returns>
        public static List<string> GetSelectionPathList(bool onlyInAssetsFolder = true)
        {
            string[] guids = Selection.assetGUIDs;
            if (guids == null || guids.Length <= 0)
            {
                return null;
            }

            List<string> selectionPathList = new List<string>();
            for (int i = 0; i < guids.Length; i++)
            {
                string path = AssetDatabase.GUIDToAssetPath(guids[i]);
                if (onlyInAssetsFolder && !path.StartsWith("Assets/"))
                {
                    continue;
                }

                selectionPathList.Add(path);
            }

            return selectionPathList;
        }

        /// <summary>
        /// 获取当前选中列表的引用
        /// </summary>
        /// <returns></returns>
        public static List<UnityEngine.Object> GetSelectionList(bool onlyInAssetsFolder = true)
        {
            string[] guids = Selection.assetGUIDs;
            if (guids == null || guids.Length <= 0)
            {
                return null;
            }

            List<UnityEngine.Object> selectionList = new List<UnityEngine.Object>();
            for (int i = 0; i < guids.Length; i++)
            {
                string path = AssetDatabase.GUIDToAssetPath(guids[i]);
                if (onlyInAssetsFolder && !path.StartsWith("Assets/"))
                {
                    continue;
                }

                selectionList.Add(AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path));
            }

            return selectionList;
        }

        #endregion

        #region 颜色相关

        /// <summary>
        /// 颜色转16进制字符串
        /// </summary>
        public static string ColorToHexString(Color32 color)
        {
            return color.r.ToString("X2") + color.g.ToString("X2") + color.b.ToString("X2");
        }

        /// <summary>
        /// 16进制字符串转颜色
        /// </summary>
        public static Color HexStringToColor(string hex)
        {
            byte r = byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber);
            byte g = byte.Parse(hex.Substring(2, 2), NumberStyles.HexNumber);
            byte b = byte.Parse(hex.Substring(4, 2), NumberStyles.HexNumber);
            return new Color32(r, g, b, 255);
        }

        #endregion

        /// <summary>
        /// 输出贴图格式
        /// </summary>
        public enum ExportTextureFormat
        {
            png,
            jpg,
            exr,
            tga,
        }

        /// <summary>
        /// 保存
        /// </summary>
        public static string SaveTexture2dToFile(string path, Texture2D texture2D, ExportTextureFormat format)
        {
            bool isFullPath = path.StartsWith(Application.dataPath);
            if (!isFullPath)
            {
                path = ChangeToFullPath(path);
            }

            switch (format)
            {
                case ExportTextureFormat.png:
                {
                    path += ".png";
                    File.WriteAllBytes(path, texture2D.EncodeToPNG());
                    break;
                }
                case ExportTextureFormat.jpg:
                {
                    path += ".jpg";
                    File.WriteAllBytes(path, texture2D.EncodeToJPG());
                    break;
                }
                case ExportTextureFormat.exr:
                {
                    path += ".exr";
                    File.WriteAllBytes(path, texture2D.EncodeToEXR());
                    break;
                }
                case ExportTextureFormat.tga:
                {
                    path += ".tga";
                    File.WriteAllBytes(path, texture2D.EncodeToTGA());
                    break;
                }
            }

            if (!isFullPath)
            {
                path = ChangeToRelativePath(path);
            }

            return path;
        }


        /// <summary>
        /// 保存
        /// </summary>
        public static string SaveTexture3dToFile(string path, Texture3D texture3D, ExportTextureFormat format)
        {
            int size3d = texture3D.width;
            int sqrtSize3d = (int)Mathf.Sqrt(size3d);
            int size2d = size3d * sqrtSize3d;
            //先Texture3d转Texture2d
            Texture2D texture2D = new Texture2D(size2d, size2d, TextureFormat.ARGB32, false);
            texture2D.wrapMode = TextureWrapMode.Mirror;
            texture2D.filterMode = FilterMode.Bilinear;
            texture2D.anisoLevel = 0;
            //颜色赋值
            Color[] pixels = texture3D.GetPixels();
            Color[] outputPixels = new Color[pixels.Length];
            for (int i = 0; i < size2d; i++)
            {
                for (int j = 0; j < size2d; j++)
                {
                    int a = i;
                    int b = j;
                    b = size2d - 1 - j;//y轴需要倒转一下
                    int x = i % size3d;
                    int x1 = (int)Mathf.Floor(i / size3d);
                    int y = j % size3d;
                    y = size3d - 1 - y;//y轴需要倒转一下
                    int y1 = (int)Mathf.Floor(j / size3d);
                    int z = y1 * sqrtSize3d + x1;
                    outputPixels[a + b * size2d] = pixels[x + y * size3d + z * size3d * size3d];
                }
            }

            texture2D.SetPixels(outputPixels);
            texture2D.Apply();
            //再Texture2d转贴图
            string p = SaveTexture2dToFile(path, texture2D, format);
            //删除texture2D
            UnityEngine.Object.DestroyImmediate(texture2D);
            return p;
        }

        /// <summary>
        /// 替换Renderer（利用反射直接修改运行时缓存参数，不影响asset资源）
        /// </summary>
        /// <param name="rendererData"></param>
        public static void ReplaceRenderer(ScriptableRendererData rendererData)
        {
            FieldInfo m_Renderers = typeof(UniversalRenderPipelineAsset).GetField("m_Renderers", BindingFlags.NonPublic | BindingFlags.Instance);
            if (rendererData != null)
            {
                MethodInfo InternalCreateRenderer = typeof(ScriptableRendererData).GetMethod("InternalCreateRenderer", BindingFlags.NonPublic | BindingFlags.Instance);
                ScriptableRenderer renderer = InternalCreateRenderer.Invoke(rendererData, null) as ScriptableRenderer;
                ScriptableRenderer[] renderers = m_Renderers.GetValue(UniversalRenderPipeline.asset) as ScriptableRenderer[];
                for (int i = 0; i < renderers.Length; i++)
                {
                    renderers[i] = renderer;
                }

                m_Renderers.SetValue(UniversalRenderPipeline.asset, renderers);
            }
            else
            {
                m_Renderers.SetValue(UniversalRenderPipeline.asset, new ScriptableRenderer[1]);
            }
        }
    }
}